# 第5章 样式处理
# 分离样式文件
webpack 4之前版本是:extract-text-webpack-plugin
webpack 4及以上版本:mini-css-extract-plugin
# extrach-text-webpack-plugin
const ExtractTextPlugin = require('extract-text-webpack-plugin');
module.exports = {
module: {
rule: [
{
test: /\.css$/,
use: ExtractTextPlugin.extract({
fallback: 'style-loader',
use: 'css-loader'
})
}
]
},
plugins: [
new ExtractTextPlugin('bundle.css');
]
}
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
fallback属性用于指定当前插件无法提取样式时所采用的loader.
# 多样式文件的处理
样式的提取是以资源入口开始的整个chunk为单位的。chunk是有一组有依赖关系的模块的封装。
const ExtractTextPlugin = require('extract-text-webpack-plugin');
module.exports = {
entry: {
foo: './src/scripts/foo.js',
bar: './src/scripts/bar.js'
},
module: {
rule: [
{
test: /\.css$/,
use: ExtractTextPlugin.extract({
fallback: 'style-loader',
use: 'css-loader'
})
}
]
},
plugins: [
new ExtractTextPlugin('[name].css');
]
}
// foo.js
// foo.css
// bar.js
// bar.css
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
# mini-css-extract-plugin
mini-css-extract-plugin是extract-text-webpack-plugin的升级版。webpack4以后使用它进行样式的提取,4之前的版本是用不了的。
它最大的特性是支持按需加载css。a.js通过import()函数异步加载了b.js,b.js里面加载了style.js,那么使用extract-text-webpack-plugin的话,style.css最终只能被同步加载。使用mini-css-extract-plugin会单独打包出一个0.css,这个css文件将由a.js通过动态插入link标签的方式加载。
const MiniCssExtractPlugin = require('mini-css-extract-plugin');
module.exports = {
entry: './app.js',
output: {
filename: '[name].js',
},
mode: 'development',
module: {
rules: [{
test: /\.css$/,
use:[
{
loader: MiniCssExtractPlugin.loader,
options: {
publicPath: '../',
}
},
'css-loader'
]
}]
},
plugin: [
new MiniCssExtractPlugin({
filename: '[name].css',
chunkFilename: '[id].css'
})
]
}
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
支持配置publicPath,用来指定异步css的加载路径。
不需要设置fallback。
除了指定同步加载的css资源名filename,还需要指定异步加载的css资源名chunkFIlename。
# 样式预处理
# sass-loader
sass-loader就是将SCSS语法编译为CSS。
npm i sass-loader node-sass
rules: [
{
test: /\.scss$/,
use: ['style-loader','css-loader','sass-loader']
}
]
2
3
4
5
6
假如想要在浏览器的调试工具中查看代码,需要分别为sass-loader和css-loader单独添加source map的配置项。
test: /\.scss$/,
use: [
'style-loader',
{
loader: 'css-loader',
options: {
sourceMap: true
}
},
{
loader: 'sass-loader',
options: {
sourceMap: true
}
},
]
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
# less
npm i less-loader less
# PostCSS
PostCSS并不是一个CSS预编译器,它只是一个编译插件的平台。它的工作模式是接收样式源代码并交由编译插件处理。PostCSS 提供了一个解析器,它能够将 CSS 解析成抽象语法树(AST),我们可以通过“插件”来传递AST,然后再把AST转换成一个串,最后再输出到目标文件中去。
rules: [
{
test: /\.scss$/,
use: [
'style-loader',
'css-loader',
'postcss-loader'
]
}
]
2
3
4
5
6
7
8
9
10
PostCSS要求必须有个单独的配置文件。webpack2中PostCSS不在支持从loader传入。需要在项目根目录下创建一个postcss.config.js。
// postcss.config.js
module.exports = {};
2
# 自动前缀
PostCSS最广泛的场景就是与Autoprefixer结合,为css自动添加厂商前缀。
npm i autoprefixer
// postcss.config.js
const autoprefixer = require('autoprefixer');
module.exports = {
plugins: [
autoprefixer({
grid: true,
browsers:[
'> 1%',
'last 3 versions',
'android 4.2',
'ie 8'
]
})
]
}
2
3
4
5
6
7
8
9
10
11
12
13
14
15
.container {
display: grid;
}
/* 编译后 */
.container {
display: -ms-grid;
display: grid;
}
2
3
4
5
6
7
8
9
# stylelint
stylelint是一个css的质量检测工具,用来统一代码风格,确保代码质量。
npm i stylelint
// postcss.config.js
const stylelint = require('stylelint');
module.exports = {
plugins: [
stylelint({
config: {
rules: {
'declaration-no-important': true
}
}
})
]
}
2
3
4
5
6
7
8
9
10
11
12
13
如果代码中出现了“!important”时就会给出警告。
# CSSNext
PostCSS可以与CSSNext结合使用,让我们在应用中使用最新的CSS语法特性。
npm i postcss-cssnext
//postcss.config.css
const postcssCssnext = require('postcss-cssnext');
module.exports = {
plugins: [
postcssCssnext({
// 指定所支持的浏览器
browsers: [
'> 1%',
'last 2 versions'
]
})
]
}
2
3
4
5
6
7
8
9
10
11
12
13
/* style.css */
:root {
--highlightColor: hwb(190, 35%, 20%);
}
body {
color: var(--highlightColor);
}
/* 打包后 */
body {
color: rgb(89, 185, 204);
}
2
3
4
5
6
7
8
9
10
11
12
# CSS Modules
CSS Modules就是把CSS模块化,让CSS也拥有模块的特点。使用CSS Modules不需要安装额外的模块,只需要开启css-loader中modules配置项。
module: {
rules: [
{
test: /\.css/,
use: [
'style-loader',
{
loader: 'css-loader',
options: {
modules: true,
localIdentName: '[name]__[local]__[hash:base64:5]',
}
}
]
}
]
}
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
localIdentName用于指明CSS代码中的类名会如何来编译。
/* style.css */
.title {
color: red;
}
/* 编译后 */
.style__title__1CFy6
2
3
4
5
6
7
使用CSS Modules时CSS文件会导出一个对象:
// style.css
.title {
color: red;
}
// app.js
import styles from './style.css';
document.write(`<h1 class="${styles.title}"></h1>`);
2
3
4
5
6
7
8
最终这个HTML中的class才能和编译后的CSS类名匹配上。